<?php

class Adept_Lifecycle
{

    private static $instance;

    protected $context = null;

    protected $ajaxMode = false;

    const RESTORE_PHASE = 1;
    const REQUEST_PHASE = 2;
    const VALIDATE_PHASE = 3;
    const UPDATE_PHASE = 4;
    const EVENT_PHASE = 5;
    const SAVE_PHASE = 6;

    protected function __construct()
    {
        $this->init();
    }

    public function init()
    {
        $this->context = Adept_Context::getInstance();
        $this->setupHttpContext();
    }

    public function setupHttpContext()
    {
        $this->context->setRequest(Adept_Request_Http::getInstance());
        $this->context->setResponse(Adept_Response_Http::getInstance());
        $this->context->setSession(Adept_Session_Http::getInstance());
    }

    public function execute()
    {
        $root = $this->getRoot();

        if ($this->ajaxMode) {
            $context = Adept_Context::getInstance();
            $context->getRequest()->convertCharset('UTF-8', 'CP1251');
        }

        //$root->processInit();
        $root->processRestore();
        $root->processRequest();
        $root->processValidate();
        $root->processUpdate();
        $root->processEvent();
        $root->processSave();
    }

    /**
     * @return Adept_Lifecycle
     */
    public static function getInstance()
    {
        if (!isset(self::$instance)) {
            self::$instance = new self();
        }
        return self::$instance;
    }

    public function getRoot()
    {
        return Adept_Context::getInstance()->getRoot();
    }

    public function render()
    {
        $response = Adept_Context::getInstance()->getResponse();

        if ($response->isRedirected()) {
            return ;
        }

        if ($this->ajaxMode) {
            $this->renderAjaxResponse();
        } else {
            $this->renderHtmlResponse();
        }
    }

    protected function renderHtmlResponse() 
    {
        $root = $this->getRoot();
        $root->render();
    }

    protected function findDirtyComponents($node) 
    {
        $result = array();
        foreach ($node->getChildren() as $component) {
            if ($component->isDirty()) {
                $result[] = $component;
            } else {
                $result = array_merge($result, $this->findDirtyComponents($component));
            }
        }
        return $result;
    }

    public function renderAjaxResponse() 
    {
        $context = ComponentsContext::getInstance();

        $request = $context->getRequest();

        $refreshString = $request->getValue('refreshComponents');


        $refreshComponents = explode(",", $refreshString);
        foreach ($refreshComponents as $refreshComponent) {

            $dirtyComponent = $this->root->findChildById($refreshComponent);
            if ($dirtyComponent) {
                $dirtyComponent->dirty();
            }
        }

        $components = $this->findDirtyComponents($this->root);


        $response = $context->getResponse();
        $response->sendHeader("content-type: text/xml \n");
        //ob_start();
        $response->write("<?xml version=\"1.0\" ?>\n");
        $response->write("<commands>");
        foreach ($components as $component) {

            $response->write("<command name=\"UpdateContentCommand\">");
            $response->write("<param name=\"container\">{$component->getId()}</param>");
            $response->write("<param name=\"content\"><![CDATA[");

            //$component->renderBegin();
            $component->renderChildren();
            //$component->renderEnd();

            $response->write("]]></param></command>");
        }
        $response->write("</commands>");

        $result = ob_get_contents();
        ob_end_clean();
        $result = iconv('CP1251', 'UTF-8', $result);
        $response->write($result);
    }

    /**
     * 
     * @param root
     */
    public function setRoot($root) 
    {
        $this->root = $root;
    }

    public function isAjaxMode() 
    {
        return $this->ajaxMode;
    }

    public function setAjaxMode($ajaxMode) 
    {
        $this->ajaxMode = $ajaxMode;
    }

}
